IAM Permissions boundary(アクセス権限の境界)で明示的に許可していないアクションでも条件次第で実行できるということを評価論理の流れを眺めて再認識してみた
コンバンハ、千葉(幸)です。
突然ですが問題です。
以下の条件があったとします。
- 同一の AWS アカウントに S3 バケット A と IAM ユーザー A が存在する
- IAM ユーザー A の Permissions boundary には AWS 管理ポリシー
ViewOnlyAccess
が設定されている
ここで、IAM ユーザー A が S3 バケット A に対してPutObject
を実行したいとします。(補足しておくと、ViewOnlyAccess
にはPutObject
の Allow は含まれていません。)
以下のうち、アクションの結果について最も適切に説明しているものを選択してください。
- IAM ユーザー A の Permissions policy で適切な Allow が設定されていればアクションは成功する
- S3 バケット A のバケットポリシーで適切な Allow が設定されていればアクションは成功する
- IAM ユーザー A の Permissions policy と S3 バケット A のバケットポリシーの両方で適切な Allow が設定されていればアクションは成功する
- どんな条件であっても Permissions boundary で
PutObject
が許可されていないためアクションは失敗する
というわけで、正解は 2. です。バケットポリシーで許可されていれば、Permissions boundary や Permissions policyで Allow が与えられていなくてもアクションは成功します。
なぜこのような挙動になるのか?その答えは「評価論理の順番がそうなっているから」なのですが、皆さんはこのあたりきちんと押さえられていましたか?
目次
Permissions boundary とは
おさらいとして、Permissions boundary とは何かを確認しておきましょう。
Permissions boundary は IAM ユーザーもしくはロールに設定することで、それらが持つ権限に境界を設定することができるものです。それに対していわゆる「 IAM ポリシー」は Permissions policy と呼ばれます。そこで定義された内容と Permissions boundary が AND 条件で評価され、「両方で許可されている」アクションのみが実行可能となる、という考え方です。
以下のような図を見たことがあるかもしれません。
(IAM エンティティのアクセス許可の境界 - AWS Identity and Access Managementより)
Permissions policy でどんなに強い権限が与えられていたとしても、Permissions boundary によって設定された境界を超えたアクションは実行できません。
主なユースケースとしては、IAM に関する強権限に制限を設ける、といった場面が考えられます。IAM 管理者に対してある程度自由な権限を与えつつも、なんでもできてしまっては困るため、クリティカルなアクションについては制限を設ける、というケースです。詳細は以下のエントリを参照してください。
ともかく、ここで許可されていないとアクションがそもそも実行できない、と思いがちな部分ではないでしょうか。私はそうでした。
評価論理とは
AWS においてアクションを実行しようとする場合、様々なポリシータイプの設定内容が評価対象となり、最終的に許可か拒否かが決定されます。
バケットポリシーや Permissions boundary も評価対象の一つです。
評価の際にはあらかじめ定義されたフローに則って行われます。それを表したものが以下です。
(ポリシーの評価論理 - AWS Identity and Access Managementより)
なお、これは実行元のプリンシパルと実行先のリソースが同一アカウントに閉じた場合にのみ有効なフローです。クロスアカウントの場合、また別の評価軸が加わります。(今回は気にしないようにしましょう。)
今回のケースを評価論理に則って順番に確認しよう
上記のフローを見てすでに皆さんは完全に理解されたかと思いますが、せっかくなので順番に確認しましょう。
明示的な拒否
まず最初はいずれかのポリシーで明示的な拒否が設定されていないかを確認します。一つ以上のポリシーで明示的な拒否が設定されていた場合、その時点でアクションは拒否されます。
冒頭の問題で 2. が正解となりうるのは、いずれのポリシーでも拒否が設定されていないことが暗黙的な前提だったりしますね。(後出しみたいですみません。)
Organizations SCP
次に Organizations SCP の評価です。アクションを実行するプリンシパルが所属するアカウントが Organizations のメンバーである場合、当該アクションが SCP で許可されていない限り拒否されます。
ここでは 当該アカウントに適用された SCP のみを考慮しますが、Organizations においては OU 間の継承という考え方があります。より複雑な世界に首を突っ込みたい方は以下エントリをご参照ください。
リソースベースポリシー
続いて今回の肝であるリソースベースポリシーです。ものすごく雑に言えば、リソースに設定するポリシーは全てリソースベースポリシーです。バケットポリシーはリソースベースポリシーに分類されます。
それに対して、IAM ユーザーやグループ、ロールといった IAM アイデンティティに設定するものはアイデンティティベースポリシーと呼ばれます。(本エントリではここまで Permissions policy と呼んでいたもの)
リソースベースポリシーで許可が設定されていれば、この段階で最終評価が許可になります。今回の例で言えば、S3 バケット A のバケットポリシーで IAM ユーザー A がPutObject
してくるのを許可していれば、この時点で許可が決定されます。Permissions boundary や Permissions policy の評価はこれより後のタイミングで行われるため、ユーザー A の設定は実は関係ないのでした。
Permissions boundary
Permissions boundary が評価対象となるのはこのタイミングです。もし今回 S3 バケットポリシーが空であれば、ここで拒否が決定されます。(ViewOnlyAccess
ではPutObject
が許可されていないため)
セッションポリシー
これはあまり耳慣れない言葉かもしれません。ロールを引き受ける(assume)際や、フェデレーティッドユーザーを使用する際にパラメータを引き渡すことによって、一時セッションにおいて有効なアクションを定義することができます。
セッション使用時にのみ有効なアクセス許可の境界を設定する、と考えるとそれなりに実態に近いかと思います。
アイデンティティベースポリシー
IAM ユーザーやロールに設定されている「いわゆる IAM ポリシー」は最後に評価されます。
いくらここで強い権限を持っていても、それより前段の評価によってアクションの実行可否は制限を受ける、ということが理解できたでしょうか。
やってみた
これで終わるのもなんなので、一応実際に試しておきます。
今回は以下のような条件で試します。
IAM ユーザー chiba-cli は以下のように Permissions boundary にViewOnlyAccess
をアタッチし、 Permissions policy は無しで設定しています。
バケットポリシーで許可している場合
バケット chiba-allow-user では以下のバケットポリシーを設定しました。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::000000000000:user/chiba-cli" }, "Action": "s3:*", "Resource": [ "arn:aws:s3:::chiba-allow-user", "arn:aws:s3:::chiba-allow-user/*" ] } ] }
プリンシパルが IAM ユーザー chiba-cli であれば、自身に対する S3 アクションは全て許可する、というポリシーです。
AWS CLI で aws s3 cp
を使用して、ローカルのファイルを S3 バケットに put します。
% aws s3 cp test.text s3://chiba-allow-user/test.text upload: ./test.text to s3://chiba-allow-user/test.text
問題なく成功しました。
バケットポリシーが空の場合
続いてバケットポリシーを設定しない S3 バケット chiba-no-bucket-policy に対して実行します。
% aws s3 cp test.text s3://chiba-no-bucket-policy/test.text upload failed: ./test.text to s3://chiba-no-bucket-policy/test.text An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
aws s3 cp
が裏側で呼び出しているPutObject
が拒否されていることが分かります。
そもそも Permissions policy に何も設定していないから当然だろうという気もしますが、評価論理としては Permissions boundary の部分で拒否されているので、Permissions policy としてAdministratorAccess
をアタッチしても結果は同じです。
終わりに
評価論理について確認しました。
このエントリを書こうと思ったのは、以下のツイートを見かけたからでした。
AWS IAM question: did you know that an Allow in a resource policy can give permission outside a principal's permissions boundary?
— Ben Kehoe (@ben11kehoe) September 15, 2020
私は力強く No に投票しました。改めて問われると理解が曖昧だったなぁという反省でこのエントリを書いてみました。参考になれば幸いです。
以上、千葉(幸)がお送りしました。